#include "ui.hpp"
#include "jatekmenet.hpp"
#include "naplo.hpp"
#include "hibakodok.hpp"

using namespace std;

Jatekmenet::Jatekmenet(int x, int y, string mi0fn, string mi1fn, Naplo *naplo) : palyaX(x), palyaY(y), naplo(naplo) {
    mi0 = new MI(mi0fn);
    mi1 = new MI(mi1fn);
    jelenlegiJatekos = 0;
    palya = new char*[x];
    for (int i = 0; i < x; i++) {
        palya[i] = new char[y];
        for (int j = 0; j < y; j++) {
            palya[i][j] = '.';
        }
    }
}

int Jatekmenet::palyaAllapot() {
    char c = '.';
    int db = 0;
    bool tele = true;
    // Egyik irany
    for (int x = 0; x < palyaX; x++) {
        for (int y = 0; y < palyaY; y++) {
            if (palya[x][y] == '.') {
                tele = false;
            }
            if (palya[x][y] == c) {
                db++;
            } else {
                db = 1;
                c = palya[x][y];
            }
            if (c != '.' && db == 5) {
                return (c == 'X') ? PALYA_ALLAPOT_X_NYERT : PALYA_ALLAPOT_O_NYERT;
            }
        }
        c = '.';
        db = 0;
    }
    if (tele) {
        return PALYA_ALLAPOT_DONTETLEN;
    }
    // Masik irany
    for (int y = 0; y < palyaY; y++) {
        for (int x = 0; x < palyaX; x++) {
            if (palya[x][y] == c) {
                db++;
            } else {
                db = 1;
                c = palya[x][y];
            }
            if (c != '.' && db == 5) {
                return (c == 'X') ? PALYA_ALLAPOT_X_NYERT : PALYA_ALLAPOT_O_NYERT;
            }
        }
        c = '.';
        db = 0;
    }
    // Egyik atlo
    // egyik fele
    for (int start = 0; start < (palyaX - 4); start++) {
        for (int i = 0; (start + i) < palyaX && i < palyaY; i++) {
            if (palya[start + i][i] == c) {
                db++;
            } else {
                db = 1;
                c = palya[start + i][i];
            }
            if (c != '.' && db == 5) {
                return (c == 'X') ? PALYA_ALLAPOT_X_NYERT : PALYA_ALLAPOT_O_NYERT;
            }
        }
        c = '.';
        db = 0;
    }
    // masik fele
    for (int start = 1; start < (palyaY - 4); start++) {
        for (int i = 0; (start + i) < palyaY && i < palyaX; i++) {
            if (palya[i][start + i] == c) {
                db++;
            } else {
                db = 1;
                c = palya[i][start + i];
            }
            if (c != '.' && db == 5) {
                return (c == 'X') ? PALYA_ALLAPOT_X_NYERT : PALYA_ALLAPOT_O_NYERT;
            }
        }
        c = '.';
        db = 0;
    }
    // Masik atlo
    // egyik fele
    for (int start = 4; start < palyaX; start++) {
        for (int i = 0; (start - i) >= 0 && i < palyaY; i++) {
            if (palya[start - i][i] == c) {
                db++;
            } else {
                db = 1;
                c = palya[start - i][i];
            }
            if (c != '.' && db == 5) {
                return (c == 'X') ? PALYA_ALLAPOT_X_NYERT : PALYA_ALLAPOT_O_NYERT;
            }
        }
        c = '.';
        db = 0;
    }
    // masik fele
    for (int start = 1; start < (palyaY - 4); start++) {
        for (int i = 0; (start + i) < palyaY && (palyaX - i - 1) >= 0; i++) {
            if (palya[palyaX - i - 1][start + i] == c) {
                db++;
            } else {
                db = 1;
                c = palya[palyaX - i - 1][start + i];
            }
            if (c != '.' && db == 5) {
                return (c == 'X') ? PALYA_ALLAPOT_X_NYERT : PALYA_ALLAPOT_O_NYERT;
            }
        }
        c = '.';
        db = 0;
    }
    return PALYA_ALLAPOT_OK;
}

int Jatekmenet::jatek() {
    if (!mi0->betolt()) {
        throw MI_BETOLTES_HIBA0;
    }
    if (!mi1->betolt()) {
        throw MI_BETOLTES_HIBA1;
    }
    naplo->fejlec();
    while (palyaAllapot() == PALYA_ALLAPOT_OK) {
        int xPozicio, yPozicio;
        if (jelenlegiJatekos == 0) {
            if (!mi0->lep(palya, palyaX, palyaY, 'X', xPozicio, yPozicio)) {
                throw MI_LEPES_HIBA0;
            } else {
                naplo->lepes(0, xPozicio, yPozicio);
            }
        } else {
            if (!mi1->lep(palya, palyaX, palyaY, 'O', xPozicio, yPozicio)) {
                throw MI_LEPES_HIBA1;
            } else {
                naplo->lepes(1, xPozicio, yPozicio);
            }
        }
        // Ellenőrizzük a lépést
        if (xPozicio < 0 || xPozicio >= palyaX
                || yPozicio < 0 || yPozicio >= palyaY
                || palya[xPozicio][yPozicio] != '.') {
            if (jelenlegiJatekos == 0) {
                naplo->lablec(PALYA_ALLAPOT_O_NYERT, INDOKLAS_ERVENYTELEN_LEPES);
                UI::vege(PALYA_ALLAPOT_O_NYERT, INDOKLAS_ERVENYTELEN_LEPES);
                return PALYA_ALLAPOT_O_NYERT;
            } else {
                naplo->lablec(PALYA_ALLAPOT_X_NYERT, INDOKLAS_ERVENYTELEN_LEPES);
                UI::vege(PALYA_ALLAPOT_X_NYERT, INDOKLAS_ERVENYTELEN_LEPES);
                return PALYA_ALLAPOT_X_NYERT;
            }
        } else {
            palya[xPozicio][yPozicio] = (jelenlegiJatekos == 0) ? 'X' : 'O';
            jelenlegiJatekos = 1 - jelenlegiJatekos;
        }
    }
    int allapot = palyaAllapot();
    int indok = (allapot == PALYA_ALLAPOT_DONTETLEN) ? INDOKLAS_PALYA_BETELT : INDOKLAS_TISZTA;
    naplo->lablec(allapot, indok);
    UI::vege(allapot, indok);
    return allapot;
}
